﻿using Org.BouncyCastle.Math;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SM
{

    public class Util
    {
        private static char[] DIGITS_LOWER = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        private static char[] DIGITS_UPPER = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

        public Util()
        {
        }

        public static byte[] intToBytes(int num)
        {
            byte[] bytes = new byte[] { (byte)(255 & num >> 0), (byte)(255 & num >> 8), (byte)(255 & num >> 16), (byte)(255 & num >> 24) };
            return bytes;
        }

        public static int byteToInt(byte[] bytes)
        {
            int num = 0;
            int temp = (255 & bytes[0]) << 0;
            num = num | temp;
            temp = (255 & bytes[1]) << 8;
            num |= temp;
            temp = (255 & bytes[2]) << 16;
            num |= temp;
            temp = (255 & bytes[3]) << 24;
            num |= temp;
            return num;
        }

        public static byte[] longToBytes(long num)
        {
            byte[] bytes = new byte[8];

            for (int i = 0; i < 8; ++i)
            {
                bytes[i] = (byte)((int)(255L & num >> i * 8));
            }

            return bytes;
        }

        public static byte[] byteConvert32Bytes(BigInteger n)
        {
            byte[] tmpd = (byte[])null;
            if (n == null)
            {
                return null;
            }
            else
            {
                if (n.ToByteArray().Length == 33)
                {
                    tmpd = new byte[32];
                    System.Array.Copy(n.ToByteArray(), 1, tmpd, 0, 32);
                }
                else if (n.ToByteArray().Length == 32)
                {
                    tmpd = n.ToByteArray();
                }
                else
                {
                    tmpd = new byte[32];

                    for (int i = 0; i < 32 - n.ToByteArray().Length; ++i)
                    {
                        tmpd[i] = 0;
                    }

                    System.Array.Copy(n.ToByteArray(), 0, tmpd, 32 - n.ToByteArray().Length, n.ToByteArray().Length);
                }

                return tmpd;
            }
        }

        public static BigInteger byteConvertInteger(byte[] b)
        {
            if (b[0] < 0)
            {
                byte[] temp = new byte[b.Length + 1];
                temp[0] = 0;
                System.Array.Copy(b, 0, temp, 1, b.Length);
                return new BigInteger(temp);
            }
            else
            {
                return new BigInteger(b);
            }
        }

        public static string getHexstring(byte[] bytes)
        {
            return getHexstring(bytes, true);
        }

        public static string getHexstring(byte[] bytes, bool upperCase)
        {
            string ret = "";

            for (int i = 0; i < bytes.Length; ++i)
            {
                ret = ret + Convert.ToString((bytes[i] & 255) + 256, 16).Substring(1);
            }

            return upperCase ? ret.ToUpper() : ret;
        }

        public static void printHexstring(byte[] bytes)
        {
            for (int i = 0; i < bytes.Length; ++i)
            {
                string hex = Convert.ToString(bytes[i] & 255);
                if (hex.Length == 1)
                {
                    hex = '0' + hex;
                }

                System.Console.Write("0x" + hex.ToUpper() + ",");
            }

            System.Console.WriteLine("");
        }

        public static byte[] hexstringToBytes(string hexstring)
        {
            if (hexstring != null && !string.IsNullOrEmpty(hexstring))
            {
                hexstring = hexstring.ToUpper();
                int Length = hexstring.Length / 2;
                char[] hexChars = hexstring.ToCharArray();
                byte[] d = new byte[Length];

                for (int i = 0; i < Length; ++i)
                {
                    int pos = i * 2;
                    d[i] = (byte)(charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
                }

                return d;
            }
            else
            {
                return null;
            }
        }

        public static byte charToByte(char c)
        {
            return (byte)"0123456789ABCDEF".IndexOf(c);
        }

        public static char[] encodeHex(byte[] data)
        {
            return encodeHex(data, true);
        }

        public static char[] encodeHex(byte[] data, bool toLowerCase)
        {
            return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
        }

        protected static char[] encodeHex(byte[] data, char[] toDigits)
        {
            int l = data.Length;
            char[] out1 = new char[l << 1];
            int i = 0;

            for (int var5 = 0; i < l; ++i)
            {
                out1[var5++] = toDigits[(240 & data[i]) >> 4];
                out1[var5++] = toDigits[15 & data[i]];
            }

            return out1;
        }

        public static string encodeHexstring(byte[] data)
        {
            return encodeHexstring(data, true);
        }

        public static string encodeHexstring(byte[] data, bool toLowerCase)
        {
            return encodeHexstring(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
        }

        protected static string encodeHexstring(byte[] data, char[] toDigits)
        {
            return new string(encodeHex(data, toDigits));
        }

        public static byte[] decodeHex(char[] data)
        {
            int len = data.Length;
            if ((len & 1) != 0)
            {
                throw new Exception("Odd number of characters.");
            }
            else
            {
                byte[] out1 = new byte[len >> 1];
                int i = 0;

                for (int j = 0; j < len; ++i)
                {
                    int f = toDigit(data[j], j) << 4;
                    ++j;
                    f |= toDigit(data[j], j);
                    ++j;
                    out1[i] = (byte)(f & 255);
                }

                return out1;
            }
        }
        public static int Digit(char value, int radix)
        {
            if ((radix <= 0) || (radix > 36))
                return -1; // Or throw exception

            if (radix <= 10)
                if (value >= '0' && value < '0' + radix)
                    return value - '0';
                else
                    return -1;
            else if (value >= '0' && value <= '9')
                return value - '0';
            else if (value >= 'a' && value < 'a' + radix - 10)
                return value - 'a' + 10;
            else if (value >= 'A' && value < 'A' + radix - 10)
                return value - 'A' + 10;

            return -1;
        }
        protected static int toDigit(char ch, int index)
        {
            int digit = Digit(ch, 16);
            if (digit == -1)
            {
                throw new Exception("Illegal hexadecimal character " + ch + " at index " + index);
            }
            else
            {
                return digit;
            }
        }

        public static string stringToAsciistring(string content)
        {
            string result = "";
            int max = content.Length;

            for (int i = 0; i < max; ++i)
            {
                char c = content[i];
                //string b = Integer.toHexstring(c);
                string b = string.Format("{0:X}", c);
                result = result + b;
            }

            return result;
        }

        public static string hexstringTostring(string hexstring, int encodeType)
        {
            string result = "";
            int max = hexstring.Length / encodeType;

            for (int i = 0; i < max; ++i)
            {
                char c = (char)hexstringToAlgorism(hexstring.Substring(i * encodeType, (i + 1) * encodeType));
                result = result + c;
            }

            return result;
        }

        public static int hexstringToAlgorism(string hex)
        {
            hex = hex.ToUpper();
            int max = hex.Length;
            int result = 0;

            for (int i = max; i > 0; --i)
            {
                char c = hex[i - 1];
                int algorism = 0;
                if (c >= '0' && c <= '9')
                {
                    algorism = c - 48;
                }
                else
                {
                    algorism = c - 55;
                }

                result = (int)((double)result + Math.Pow(16.0D, (double)(max - i)) * (double)algorism);
            }

            return result;
        }

        public static string hexstringToBinary(string hex)
        {
            hex = hex.ToUpper();
            string result = "";
            int max = hex.Length;

            for (int i = 0; i < max; ++i)
            {
                char c = hex[i];
                switch (c)
                {
                    case '0':
                        result = result + "0000";
                        break;
                    case '1':
                        result = result + "0001";
                        break;
                    case '2':
                        result = result + "0010";
                        break;
                    case '3':
                        result = result + "0011";
                        break;
                    case '4':
                        result = result + "0100";
                        break;
                    case '5':
                        result = result + "0101";
                        break;
                    case '6':
                        result = result + "0110";
                        break;
                    case '7':
                        result = result + "0111";
                        break;
                    case '8':
                        result = result + "1000";
                        break;
                    case '9':
                        result = result + "1001";
                        break;
                    case 'A':
                        result = result + "1010";
                        break;
                    case 'B':
                        result = result + "1011";
                        break;
                    case 'C':
                        result = result + "1100";
                        break;
                    case 'D':
                        result = result + "1101";
                        break;
                    case 'E':
                        result = result + "1110";
                        break;
                    case 'F':
                        result = result + "1111";
                        break;
                    case ':':
                    case ';':
                    case '<':
                    case '=':
                    case '>':
                    case '?':
                    case '@':
                    default:
                        break;
                }
            }

            return result;
        }

        public static string AsciistringTostring(string content)
        {
            string result = "";
            int Length = content.Length / 2;

            for (int i = 0; i < Length; ++i)
            {
                string c = content.Substring(i * 2, i * 2 + 2);
                int a = hexstringToAlgorism(c);
                char b = (char)a;
                string d = b.ToString();
                result = result + d;
            }

            return result;
        }

        public static string algorismToHexstring(int algorism, int maxLength)
        {
            string result = "";
            //result = Integer.toHexstring(algorism);
            result = string.Format("{0:X}", algorism);
            if (result.Length % 2 == 1)
            {
                result = "0" + result;
            }

            return patchHexstring(result.ToUpper(), maxLength);
        }

        public static string byteTostring(byte[] bytearray)
        {
            string result = "";
            int Length = bytearray.Length;

            for (int i = 0; i < Length; ++i)
            {
                char temp = (char)bytearray[i];
                result = result + temp;
            }

            return result;
        }

        public static int binaryToAlgorism(string binary)
        {
            int max = binary.Length;
            int result = 0;

            for (int i = max; i > 0; --i)
            {
                char c = binary[i - 1];
                int algorism = c - 48;
                result = (int)((double)result + Math.Pow(2.0D, (double)(max - i)) * (double)algorism);
            }

            return result;
        }

        public static string algorismToHEXstring(int algorism)
        {
            string result = "";
            // result = Integer.toHexstring(algorism);
            result = string.Format("{0:X}", algorism);
            if (result.Length % 2 == 1)
            {
                result = "0" + result;
            }

            result = result.ToUpper();
            return result;
        }

        public static string patchHexstring(string str, int maxLength)
        {
            string temp = "";

            for (int i = 0; i < maxLength - str.Length; ++i)
            {
                temp = "0" + temp;
            }

            str = (temp + str).Substring(0, maxLength);
            return str;
        }

        public static int parseToInt(string s, int defaultInt, int radix)
        {
            bool var3 = false;

            int i;
            try
            {
                i = Convert.ToInt32(s, radix);
            }
            catch (Exception var5)
            {
                i = defaultInt;
            }

            return i;
        }

        public static int parseToInt(string s, int defaultInt)
        {
            bool var2 = false;

            int i;
            try
            {
                i = Convert.ToInt32(s);
            }
            catch (Exception var4)
            {
                i = defaultInt;
            }

            return i;
        }

        public static byte[] hexToByte(string hexString)
        {
            //if (hex.Length % 2 != 0) {
            //        throw new Exception();
            //} else {
            //    char[] arr = hex.ToCharArray();
            //    byte[] b = new byte[hex.Length / 2];
            //    int i = 0;
            //    int j = 0;

            //    for(int l = hex.Length; i<l; ++j) {
            //        string swap = "" + arr[i++] + arr[i];
            //        int byteint = Convert.ToInt32(swap,16) & 255;
            //        b[j] = Convert.ToByte(swap);
            //        ++i;
            //    }

            //return b;
            byte[] bytes = new byte[hexString.Length / 2];
            for (int i = 0; i < hexString.Length; i += 2)
            {
                string s = hexString.Substring(i, 2);
                bytes[i / 2] = byte.Parse(s, NumberStyles.HexNumber, null);
            }
            return bytes;

        }

        public static string byteToHex(byte[] b)
        {
            if (b == null)
            {
                throw new Exception("Argument b ( byte array ) is null! ");
            }
            else
            {
                string hs = "";
                string stmp = "";

                for (int n = 0; n < b.Length; ++n)
                {
                    // stmp = Integer.toHexstring(b[n] & 255);
                    stmp = string.Format("{0:X}", b[n]);
                    if (stmp.Length == 1)
                    {
                        hs = hs + "0" + stmp;
                    }
                    else
                    {
                        hs = hs + stmp;
                    }
                }

                return hs.ToUpper();
            }
        }

        public static byte[] subByte(byte[] input, int startIndex, int Length)
        {
            byte[] bt = new byte[Length];

            for (int i = 0; i < Length; ++i)
            {
                bt[i] = input[i + startIndex];
            }

            return bt;
        }
    }
}
